package za.co.entelect.challenge.dto.reader; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import net.minidev.json.JSONArray; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.PathNotFoundException; import za.co.entelect.challenge.dto.GameState; import za.co.entelect.challenge.dto.Missile; import za.co.entelect.challenge.dto.Player; import za.co.entelect.challenge.dto.Ship; import za.co.entelect.challenge.dto.enums.EntityType; import za.co.entelect.challenge.utils.LogHelper; /** * This class accesses the json elements directly * Advantage: Fast and no need initialise everything - only use what you need * Disadvantage: Match/Game State model only partially initialised */ public class BasicGameStateReader implements GameStateReader { @Override public GameState read(File jsonFile) throws IOException { try { GameState gameState = new GameState(); loadRoundNumber(jsonFile, gameState); String player1Path = "$.Players[0]"; String player2Path = "$.Players[1]"; Player player1 = loadPlayer(jsonFile, player1Path); Player player2 = loadPlayer(jsonFile, player2Path); gameState.getPlayers().add(player1); gameState.getPlayers().add(player2); return gameState; } catch (NumberFormatException nfe) { throw new RuntimeException("Unable to convert Round Number to int", nfe); } } private void loadRoundNumber(File jsonFile, GameState gameState) throws IOException { String roundNumber = "$.RoundNumber"; gameState.setRoundNumber(Integer.valueOf(JsonPath.read(jsonFile, roundNumber).toString())); } private Player loadPlayer(File jsonFile, String playerPath) throws IOException { Player player = new Player(); try { Map<String, Object> playerMap = JsonPath.read(jsonFile, playerPath); player.setPlayerName((String)playerMap.get("PlayerName")); player.setPlayerNumber((Integer)playerMap.get("PlayerNumber")); player.setPlayerNumberReal((Integer)playerMap.get("PlayerNumberReal")); player.setKills((Integer)playerMap.get("Kills")); player.setLives((Integer)playerMap.get("Lives")); player.setMissileLimit((Integer)playerMap.get("MissileLimit")); JSONArray missiles = (JSONArray)playerMap.get("Missiles"); player.setMissiles(loadMissiles(missiles)); Ship ship = loadShip ((Map)playerMap.get("Ship")); player.setShip(ship ); } catch (PathNotFoundException pnfe) { LogHelper.log("Index out of bounds when evaluating path " + playerPath); pnfe.printStackTrace(); } return player; } private Ship loadShip(Map<String,Object> in) { Ship ship = new Ship(); ship.setAlive((Boolean) in.get("Alive")); ship.setCommand(in.get("Command").toString()); ship.setCommandFeedback(in.get("CommandFeedback").toString()); ship.setHeight((Integer) in.get("Height")); ship.setId((Integer) in.get("Id")); ship.setPlayerNumber((Integer) in.get ("PlayerNumber")); ship.setType((String) in.get("Type")); ship.setWidth((Integer) in.get ("Width")); ship.setX((Integer) in.get("X")); ship.setY((Integer) in.get("Y")); return ship; } private List<Object> loadMissiles(JSONArray missiles) { List<Object> playerMissiles = new ArrayList<>(); Missile playerMissile; for (Object missile : missiles) { playerMissile = new Missile(); @SuppressWarnings("unchecked") LinkedHashMap<String, Object> playerMissilesMap = (LinkedHashMap<String, Object>) missile; playerMissile.setAlive((Boolean)playerMissilesMap.get("Alive")); playerMissile.setX((Integer)playerMissilesMap.get("x")); playerMissile.setY((Integer)playerMissilesMap.get("y")); playerMissile.setWidth((Integer)playerMissilesMap.get("Width")); playerMissile.setHeight((Integer)playerMissilesMap.get("Height")); for (EntityType type : EntityType.values()) { if (((String)playerMissilesMap.get("Type")).equalsIgnoreCase(type.toString())) { playerMissile.setType(type); break; } } playerMissile.setPlayerNumber((Integer)playerMissilesMap.get("PlayerNumber")); playerMissile.setActionRate((Integer)playerMissilesMap.get("ActionRate")); playerMissiles.add(playerMissile); } return playerMissiles; } }